Skip to content

Implement Michigan Child Care Assistance Program (CDC)#8627

Open
hua7450 wants to merge 9 commits into
PolicyEngine:mainfrom
hua7450:mi-ccap
Open

Implement Michigan Child Care Assistance Program (CDC)#8627
hua7450 wants to merge 9 commits into
PolicyEngine:mainfrom
hua7450:mi-ccap

Conversation

@hua7450

@hua7450 hua7450 commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements the Michigan Child Development and Care (CDC) program — Michigan's CCDF child care subsidy (family brand "CDC Scholarship") — in PolicyEngine. The CDC subsidy is a provider reimbursement, not a percent-of-income copay: each eligible child's subsidy is the department hourly rate (looked up by provider type × star rating × age group) multiplied by block hours, capped at the child's authorized hours, minus a flat Family Contribution. Income only gates entry/exit eligibility and selects the Family Contribution band; it never scales the subsidy by a percentage.

This PR covers the current era only. The 2025-09-21 income/Family-Contribution scale and the highest-hours two-parent rule (effective 2024-11-03) are encoded at their actual effective dates. Prior-era values are documented in Historical Notes below for a follow-up backdating PR.

Closes #8626

Regulatory Authority

Administered by MiLEAP (Michigan Department of Lifelong Education, Advancement and Potential); eligibility is determined through MDHHS Bridges, and policy lives in the MDHHS Bridges Eligibility Manual (BEM), so files use the mdhhs agency segment.

Income Eligibility Tests

A family qualifies through one of six eligibility groups; all groups are subject to the $1,000,000 asset test (BEM 703 p.14, the CCDF asset rule — effectively non-binding). Protective-services groups are assessed before income.

Five income-waived groups (no income test, Family Contribution waived):

Group How modeled Source
Children's Protective Services receives_or_needs_protective_services BEM 703 p.15
Foster Care is_in_foster_care BEM 703 p.15
FIP-related (child or parent receives FIP or SSI) is_tanf_enrolled (MI FIP = TANF) or ssi > 0 BEM 703 p.16
Homeless (McKinney-Vento) is_homeless BEM 703 p.16
Migrant farmworkers Not modeled (see below) BEM 703 p.16

Income-eligible group (income test + Family Contribution): gross monthly income of the program group must be at or below the entry limit at application and at or below the exit limit ongoing (BEM 703 p.17). The initial-applicant vs. enrolled-recipient distinction is modeled via the mi_ccap_enrolled boolean input, mirroring the two-threshold pattern used by NJ and WV.

Income Deductions & Exemptions

The CDC program counts the gross monthly income of the program group (BEM 703 p.13); there are no standard deductions. Counted income sources (income/countable_income/sources.yaml): employment income, self-employment income, Social Security retirement/disability/survivors, dividend income, interest income, rental income, pension income, veterans' benefits, unemployment compensation, workers' compensation, alimony income, and child support received. SSI is not counted — the State Plan (§2.2.4.c) leaves public assistance uncounted, and SSI recipients are an income-waived group regardless (so it would never affect the income test or Family Contribution band).

Grandparent/guardian parent-substitute income is excluded by the manual (BEM 703 p.13) but is not separately tracked in the model (partial — noted below).

Income Standards

RFT 270 Table 1 (effective 2025-09-21). Columns are maximum monthly gross income. The Entry limit is column 2 of the seven-column table; the Exit limit is column 7. (Column 1 is an unlabeled lowest band that pairs with $0 Family Contribution. The header verification corrected the "Entry"/"Exit" label placement; the data values were already correct.) A single parent applying for one child is family size 2; family size 1 arises from the program-group definition. The scale stops at family size 10.

Basis of the limits (confirmed against the FFY 2025–2027 State Plan): entry is 200% FPL and exit is 85% SMI. The State Plan expresses entry as a percent of SMI (54–58% by family size, §2.2.4) for federal reporting but states the limits are "established and reported in terms of current SMI … even if the federal poverty level is used in implementing the program," and confirms explicitly that "program entrance is at 55% SMI (200% FPL)" for a family of three. These limits are therefore transcribed as dollar amounts from RFT 270 rather than computed as a live rate × FPG/SMI, because the published table is single-dated and rounded — a live rate would drift from the official figures as FPG and SMI uprate.

Family Size Entry Limit (monthly) Exit Limit (monthly)
1 $2,608 $4,311
2 $3,526 $5,638
3 $4,442 $6,964
4 $5,358 $8,291
5 $6,276 $9,617
6 $7,192 $10,944
7 $8,108 $11,192
8 $9,026 $11,441
9 $9,942 $11,690
10 $10,858 $11,938

Benefit Calculation

The per-child biweekly subsidy is min(block_hours, authorized_hours) × hourly_rate − family_contribution, floored at zero, summed across the SPM unit, then converted from a two-week pay period to monthly using WEEKS_IN_YEAR / 2 / MONTHS_IN_YEAR (= 2.16667). mi_child_care_subsidies (YEAR) aggregates this into the federal child_care_subsidies total.

Authorized hours (authorized_hours/tiers.yaml, BEM 710 p.1 / BEM 706 p.2, p.13): biweekly need hours map to one of the tiers 20 / 40 / 60 / 80 / 90, capped at 90 per child per pay period. Need hours derive from each parent's activity hours (weekly_hours_worked_before_lsr). For two-parent households the program authorizes on the parent with the highest need hours (effective 2024-11-03; two_parent_uses_highest_hours.yaml), implemented as spm_unit.max over head/spouse hours. The meal-period, study/lab, and travel add-ons in the full BEM 710 need calculation are not tracked, so authorized hours are based on base activity hours only (partial).

Block reimbursement (block_hours/tiers.yaml, BEM 706 p.9, effective 2022-10-09): for Centers and Group & Family Homes, billing 1–30 hours pays the hourly rate × 30, 31–60 hours × 60, and 61+ hours × 90, then capped at the child's authorized hours. License-exempt providers have no block rate — they are paid hourly (hours × rate), capped at authorized hours (BEM 706 p.11; RFT 270 p.7). In a model without a separate "hours billed" input, paid hours equal the authorized tier at every tier.

Hourly rate (rates/center.yaml, rates/family_home.yaml, rates/exempt.yaml, RFT 270 p.4, effective 2024-09-22): a three-dimensional lookup over provider type × star/quality level × age group. Age groups (age_group/thresholds.yaml, RFT 270 p.4) are Infant/Toddler (birth up to 2.5 years), Preschool (2.5 up to 5), and School Age (5 and over). Licensed providers (Center, Group & Family Home) use 5 distinct star tiers (Base/1-Star collapse to one rate; then 2/3/4/5-Star); license-exempt providers use Level 1 / Level 2 only.

Family Contribution (family_contribution/per_child.yaml, RFT 270 p.3 / BEM 706 p.2): a flat per-child, per-pay-period dollar amount set by the income band the program-group income falls in — $0 / $15 / $30 / $45 / $60 / $69 / $78 across the seven columns — subtracted from the provider payment. It is waived (family_contribution/star_waiver_threshold.yaml) for any income-waived child and for income-eligible children at a licensed 3-Star (Enhancing Quality) or higher provider. License-exempt providers have no Great Start to Quality rating, so their income-eligible children always pay regardless of any star rating on record (RFT 270 p.3); the waiver is gated on provider type, not the star rating alone. The summed per-child Family Contribution is capped at a per-family limit (family_contribution/family_limit.yaml): N/A / $45 / $83 / $121 / $143 / $164 / $186 across the seven bands.

Requirements Coverage

31 of 38 identified requirements are implemented; 7 are excluded by design (below).

REQ Description Param Variable Test
001 Child under 13 age-eligible; must be a tax-unit dependent eligibility/child_age_limit mi_ccap_eligible_child (is_tax_unit_dependent) mi_ccap_eligible_child
002 Child 13–<18 if constant care (is_disabled proxy) eligibility/disabled_child_age_limit mi_ccap_eligible_child mi_ccap_eligible_child
005 Immigration status (reused CCDF check) mi_ccap_eligible_child (is_ccdf_immigration_eligible_child) mi_ccap_eligible_child
006 Each parent needs a valid need reason; both in two-parent HH mi_ccap_activity_eligible mi_ccap_activity_eligible
007 Need reason: family preservation (partial) mi_ccap_activity_eligible (receives_or_needs_protective_services) mi_ccap_activity_eligible
008 Need reason: high school completion mi_ccap_activity_eligible (is_full_time_student) mi_ccap_activity_eligible
009 Need reason: approved activity (job search, training, treatment) mi_ccap_activity_eligible (is_full_time_student, with meets_ccdf_activity_test fallback for activities not modeled individually) mi_ccap_activity_eligible
010 Need reason: employment/self-employment mi_ccap_activity_eligible (weekly_hours_worked_before_lsr) mi_ccap_activity_eligible
012 Income-waived: CPS mi_ccap_income_waived mi_ccap_income_waived
013 Income-waived: Foster Care mi_ccap_income_waived mi_ccap_income_waived
014 Income-waived: FIP/SSI mi_ccap_income_waived (is_tanf_enrolled | ssi>0) mi_ccap_income_waived
015 Income-waived: Homeless mi_ccap_income_waived mi_ccap_income_waived
017 Entry limit at application, exit limit ongoing income/scale/entry_limit, exit_limit mi_ccap_income_eligible, mi_ccap_enrolled mi_ccap_income_eligible
018 Asset ≤ $1,000,000 (reused CCDF check) mi_ccap_eligible (is_ccdf_asset_eligible) mi_ccap_eligible
019 Biweekly need hours (partial — base activity only) authorized_hours/tiers mi_ccap_authorized_hours mi_ccap_authorized_hours
020 Two-parent: highest need hours (eff 2024-11-03) two_parent_uses_highest_hours mi_ccap_authorized_hours mi_ccap_authorized_hours
021 Authorized tiers 20/40/60/80/90; max 90 authorized_hours/tiers mi_ccap_authorized_hours mi_ccap_authorized_hours
022 Block reimburse Center/FCC (1-30→30, 31-60→60, 61+→90) block_hours/tiers mi_ccap_block_payment mi_ccap_block_payment
023 License-exempt hourly, no block mi_ccap_block_payment mi_ccap_block_payment
024 Hourly rate = provider type × star × age rates/center, family_home, exempt mi_ccap_hourly_rate mi_ccap_hourly_rate
025 Age groups (Inf/Tod <2.5, Preschool 2.5–5, School 5+) age_group/thresholds mi_ccap_age_group mi_ccap_age_group
026 Family size = CDC program group; cap 10 eligibility/max_program_group_size mi_ccap_program_group_size mi_ccap_program_group_size
027 Gross monthly income of program group (partial — grandparent/guardian exclusion not tracked) income/countable_income/sources mi_ccap_countable_income integration
028 Income Eligibility Scale by family size income/scale/band_thresholds/size_1..10 mi_ccap_income_eligible, mi_ccap_family_contribution mi_ccap_income_eligible, mi_ccap_family_contribution
029 Family Contribution flat per-child per band family_contribution/per_child mi_ccap_family_contribution mi_ccap_family_contribution
030 FC subtracted from provider payment mi_ccap integration
031 FC waived for income-waived children and income-eligible children at licensed 3-star+ providers (license-exempt always pays) family_contribution/star_waiver_threshold mi_ccap_family_contribution mi_ccap_family_contribution, integration
032 Per-family FC limit per band family_contribution/family_limit mi_ccap_family_contribution mi_ccap_family_contribution, integration
036 Provider type input enum mi_ccap_provider_type mi_ccap_hourly_rate, mi_ccap_block_payment
037 Star/quality input enum mi_ccap_star_rating, mi_ccap_exempt_level mi_ccap_hourly_rate

Not Modeled

What Source Why excluded
Court-supervision age extension (children 13–<18 under court supervision) BEM 703 p.1; State Plan §2.2.1.c Court-supervision status not tracked
Turns-13-mid-period 12-month continuity BEM 703 p.2 Framework evaluates a static point in time; within-year continuous-eligibility carry-over not tracked
License-exempt provider as the only need reason being invalid BEM 703 p.12 Provider-as-need-reason not tracked
Migrant farmworker income-waived group BEM 703 p.16 No existing migrant variable; tiny microdata population (user decision)
Absence cap (360 hr/fiscal year) BEM 706 p.13 Within-year attendance/absence tracking not simulatable
Provider registration/annual fees ($65 center / $40 home) BEM 706 p.13; RFT 270 p.2 Provider-side discretionary fees, not a household benefit
Provider biweekly hour caps BEM 706 p.13 Provider-total administrative caps, not per-child

Historical Notes

The following prior-era values were identified during research but are not encoded here — they are recorded for a follow-up backdating PR:

  • Income/Family-Contribution scale: the encoded RFT 270 Table 1 scale is effective 2025-09-21. A prior scale was effective 2024-09-22 (superseded by the current one). Source: RFT 270 p.3.
  • Two-parent authorization rule: the encoded rule authorizes on the parent with the highest need hours, effective 2024-11-03. Before 2024-11-03 the program authorized on the parent with the fewest hours. Source: BEM 710 p.2.
  • Hourly rates: the encoded rates (RFT 270 Table 2) are effective 2024-09-22 (Pay Period 420) and remain current; the block reimbursement schedule has been effective since 2022-10-09.

Files Added

changelog.d/
  mi-ccap.added.md
policyengine_us/
  parameters/gov/hhs/ccdf/
    child_care_subsidy_programs.yaml          (modified — added mi_child_care_subsidies)
  programs.yaml                                (modified — added Michigan CDC entry + CCDF coverage)
  parameters/gov/states/mi/mdhhs/ccap/
    age_group/thresholds.yaml
    authorized_hours/tiers.yaml
    block_hours/tiers.yaml
    eligibility/child_age_limit.yaml
    eligibility/disabled_child_age_limit.yaml
    eligibility/max_program_group_size.yaml
    family_contribution/per_child.yaml
    family_contribution/family_limit.yaml
    family_contribution/star_waiver_threshold.yaml
    income/countable_income/sources.yaml
    income/scale/entry_limit.yaml
    income/scale/exit_limit.yaml
    income/scale/band_thresholds/size_1.yaml ... size_10.yaml
    rates/center.yaml
    rates/family_home.yaml
    rates/exempt.yaml
    two_parent_uses_highest_hours.yaml
  variables/gov/states/mi/mdhhs/ccap/
    mi_ccap.py
    mi_child_care_subsidies.py
    mi_ccap_age_group.py
    mi_ccap_authorized_hours.py
    mi_ccap_block_payment.py
    mi_ccap_countable_income.py
    mi_ccap_enrolled.py
    mi_ccap_exempt_level.py
    mi_ccap_family_contribution.py
    mi_ccap_hourly_rate.py
    mi_ccap_program_group_size.py
    mi_ccap_provider_type.py
    mi_ccap_star_rating.py
    eligibility/mi_ccap_eligible.py
    eligibility/mi_ccap_eligible_child.py
    eligibility/mi_ccap_income_eligible.py
    eligibility/mi_ccap_income_waived.py
    eligibility/mi_ccap_activity_eligible.py
  tests/policy/baseline/gov/states/mi/mdhhs/ccap/
    integration.yaml
    mi_ccap_age_group.yaml
    mi_ccap_authorized_hours.yaml
    mi_ccap_block_payment.yaml
    mi_ccap_family_contribution.yaml
    mi_ccap_hourly_rate.yaml
    mi_ccap_program_group_size.yaml
    eligibility/mi_ccap_eligible.yaml
    eligibility/mi_ccap_eligible_child.yaml
    eligibility/mi_ccap_income_eligible.yaml
    eligibility/mi_ccap_income_waived.yaml
    eligibility/mi_ccap_activity_eligible.yaml

Test plan

  • 113 tests pass (policyengine-core test policyengine_us/tests/policy/baseline/gov/states/mi/mdhhs/ccap -c policyengine_us)
  • make format clean
  • CI passes

🤖 Generated with Claude Code

hua7450 and others added 3 commits June 12, 2026 12:03
Scaffolds the branch for Michigan's Child Development and Care (CDC)
program, the state's CCDF-funded child care subsidy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.31507% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.31%. Comparing base (fbace93) to head (0af1243).
⚠️ Report is 18 commits behind head on main.

Files with missing lines Patch % Lines
...v/states/mi/mdhhs/ccap/mi_ccap_authorized_hours.py 90.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##              main    #8627      +/-   ##
===========================================
- Coverage   100.00%   99.31%   -0.69%     
===========================================
  Files            1       18      +17     
  Lines           23      292     +269     
  Branches         0        1       +1     
===========================================
+ Hits            23      290     +267     
- Misses           0        1       +1     
- Partials         0        1       +1     
Flag Coverage Δ
unittests 99.31% <99.31%> (-0.69%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

hua7450 and others added 4 commits June 12, 2026 17:15
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Gate family-contribution star waiver to licensed providers; license-exempt
  children always pay regardless of any star rating on record (RFT 270 p.3).
- Remove SSI from countable income; State Plan §2.2.4.c leaves public
  assistance uncounted, and SSI recipients are income-waived anyway.
- Add meets_ccdf_activity_test fallback for approved BEM 703 need reasons we
  don't model individually (job search, education/training, treatment).
- Require tax-unit dependent status for an eligible child.
- Fix eligible-child comment: the unmodeled over-13 pathway is court
  supervision, not high-school completion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…into mi-ccap

# Conflicts:
#	policyengine_us/programs.yaml
@hua7450 hua7450 marked this pull request as ready for review June 15, 2026 21:18
hua7450 and others added 2 commits June 15, 2026 20:14
mi_ccap_program_group_size is MI-scoped, so non-MI SPM units report size 0.
defined_for masks the result but the income-eligible formula still runs
vectorized over every unit, and the size-indexed entry/exit breakdown lookup
raised ParameterNotFoundError on the masked-out (size 0) rows in
microsimulation. Clamp the lookup index to the scale minimum of 1. Unit tests
pass because every test household is MI with size >= 1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Michigan Child Care Assistance Program (CCAP / Child Development and Care - CDC)

1 participant